#region Summary

// 
// Owner : JackieHan 
// 
// Solution : WebShopApi 
// 
// Project : Jackie.Utility
// 
// File : SerializerUtils.cs
// 
// CopyRight : Copyright © 2010-2011 Skomart Corporation, All Rights Reserved 
// 
// Summary : 序列化工具类
// 
// History : 
//			2011-04-19 10:57:32	    Create 
// 

#endregion

#region Using

using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
using System.Text.RegularExpressions;
using System.Xml;
using System.Xml.Serialization;
using Jackie.Utility.CustomExtension;

#endregion

namespace Jackie.Utility.Web
{
    /// <summary> 
    /// 序列化工具类
    /// </summary>
    public class SerializerUtils<T> where T : class
    {
        private static readonly Regex Regex = new Regex("<(\\w+?)[ >]", RegexOptions.Compiled);

        private static readonly IDictionary<string, XmlSerializer> OverrideRootSerializers =
            new Dictionary<string, XmlSerializer>();

        /// <summary>
        /// 重写Root属性的反序列化
        /// </summary>
        /// <remarks>
        /// 使用这个方法进行反序列化，可以不考虑反序列化对象的RootAttribute属性，直接用xml的根元素做为对象的Root
        /// </remarks>
        /// <param name="xmlStr">xml字符串</param>
        /// <returns></returns>
        public T DeserializeWithOverrideRoot(string xmlStr)
        {
            var rootTagName = GetRootElement(xmlStr);
            XmlSerializer serializer;
            if (!OverrideRootSerializers.ContainsKey(rootTagName))
            {
                var rootAttrs = new XmlAttributes { XmlRoot = new XmlRootAttribute(rootTagName) };
                var attrOverrides = new XmlAttributeOverrides();
                attrOverrides.Add(typeof(T), rootAttrs);

                serializer = new XmlSerializer(typeof(T), attrOverrides);
                if (!OverrideRootSerializers.ContainsKey(rootTagName))
                {
                    OverrideRootSerializers.Add(rootTagName, serializer);
                }
            }
            else
                serializer = OverrideRootSerializers[rootTagName];

            using (var stream = new MemoryStream(Encoding.UTF8.GetBytes(xmlStr)))
            {
                return serializer.Deserialize(stream) as T;
            }
        }

        private string GetRootElement(string body)
        {
            var match = Regex.Match(body);
            if (match.Success)
            {
                return match.Groups[1].ToString();
            }
            else
            {
                throw new XmlException("Invalid Xml format!");
            }
        }
    }
}